package libretto.connection;

import java.io.IOException;
import java.net.ConnectException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.security.auth.login.LoginException;

public class ConnectionManager {

	public static final String TAG = ConnectionManager.class.getName();
	public static final int MAX_CONNECTIONS = 2;

	private static ConnectionManager instance;
	private static KeyStore trustStore;

	private ArrayList<Runnable> active;
	private ArrayList<Runnable> queue;

	private Esse3HttpClient esse3;
	private SsolHttpClient ssol;

	private HttpConnection ssolConn;
	private HttpConnection esse3Conn;

	private ConnectionManager() {
		active = new ArrayList<Runnable>();
		queue = new ArrayList<Runnable>();
	}

	public static ConnectionManager getInstance() {
		if (instance == null)
			instance = new ConnectionManager();
		return instance;
	}

	public static KeyStore getTrustStore(String url, int port)
			throws KeyManagementException, KeyStoreException,
			NoSuchAlgorithmException, CertificateException, IOException {
		if (trustStore == null) {
			trustStore = new InstallCert(url, port).getUpdatedTrustStore();
		}

		return trustStore;
	}

	public void authenticate(String user, String pass) throws ConnectException,
			LoginException {
		// Login presso univr.esse3.cineca.it
		esse3 = new Esse3HttpClient(user, pass);
		esse3Conn = new HttpConnection(esse3);

		// Login presso www.ssol.univr.it
		ssol = new SsolHttpClient();
		ssolConn = new HttpConnection(ssol);
		Map<String, String> params = new HashMap<String, String>();
		params.put("username", user);
		params.put("password", pass);
		ssolConn.post(SsolHttpClient.AUTH_URI + "main?ent=login", params);
	}

	public void push(Runnable next) {
		queue.add(next);
		if (active.size() < MAX_CONNECTIONS)
			startNext();
	}

	public void didComplete(HttpConnection httpConn) {
		active.remove(httpConn);
		startNext();
	}

	public void reset() {
		if (ssolConn != null) {
			ssolConn.reset();
		}
		if (esse3Conn != null) {
			esse3Conn.reset();
		}

		instance = null;
	}

	private void startNext() {
		if (!queue.isEmpty()) {
			Runnable next = queue.get(0);
			queue.remove(0);
			active.add(next);

			next.run();
		}
	}

	public HttpConnection getEsse3Connection() {
		return esse3Conn;
	}

	public HttpConnection getSsolConnection() {
		return ssolConn;
	}
}
